import utils from '../core/utils';
import logger from '../core/logger';
import apiInfo from './core/apiInfo';
import current from '../core/current';
import dataInfo from './core/dataInfo';
import apiProvider from './core/apiProvider';
import smsModel from '../model/user/smsModel';
import userInfo from '../model/user/userInfo';
import { clientBase } from './core/clientBase';
import userAtList from '../model/user/userAtList';
import countryItem from '../model/user/countryItem';
import returnModel from '../model/common/returnModel';
import loginCallback from '../model/user/loginCallback';
import homeUserCardModel from '../model/user/homeUserCardModel';

class userClient extends clientBase {
  constructor() {
    super();
  }

  getCountry(): Promise<returnModel<Array<countryItem>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://passport.bilibili.com/x/passport-login/country");
        this.client.getResult(info, apiProvider.LoginKey).then((res) => {
          if (res.code == 0) {
            var data = res.data.list as Array<countryItem>;
            resolve(self.buildSuccessResult<Array<countryItem>>(data));
          } else
            resolve(self.buildFailedResult<Array<countryItem>>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(this.buildExceptionResult<Array<countryItem>>(e));
      }
    });
  }

  sendSms(cid: string, phone: string, sessionId: string, seccode: string, validate: string, challenge: string, token: string): Promise<returnModel<smsModel>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info: dataInfo;
        if (utils.isEmpty(validate)) {
          info = new dataInfo(`channel=bili&cid=${cid}&tel=${phone}&login_session_id=${sessionId}&statistics=${encodeURIComponent('{"appId":1,"platform":3,"version":"7.27.0","abtest":""}')}&buvid=${current.instance.buvid}&local_id=${current.instance.buvid}`, apiProvider.Build7);
        } else {
          info = new dataInfo(`channel=bili&cid=${cid}&tel=${phone}&login_session_id=${sessionId}&statistics=${encodeURIComponent('{"appId":1,"platform":3,"version":"7.27.0","abtest":""}')}&buvid=${current.instance.buvid}&local_id=${current.instance.buvid}&gee_seccode=${seccode}&gee_validate=${validate}&gee_challenge=${challenge}&recaptcha_token=${token}`, apiProvider.Build7);
        }
        this.client.postResult("https://passport.bilibili.com/x/passport-login/sms/send", info, apiProvider.LoginKey).then((res) => {
          if (res.code == 0) {
            var url = res.data.recaptcha_url;
            var key = res.data.captcha_key;
            resolve(self.buildSuccessResult<smsModel>(new smsModel(key, url)));
          } else
            resolve(self.buildFailedResult<smsModel>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<smsModel>(e));
      }
    });
  }

  smsLogin(cid: string, phone: string, sessionId: string, captchaKey: string, code: string): Promise<returnModel<loginCallback>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new dataInfo(`cid=${cid}&tel=${phone}&login_session_id=${sessionId}&captcha_key=${captchaKey}&code=${code}`,
          apiProvider.Build7);
        this.client.postResult('https://passport.bilibili.com/x/passport-login/login/sms', info, apiProvider.LoginKey).then((res) => {
          if (res.code == 0 && res.data.status == 0) {
            var mid = res.data.token_info.mid.toString();
            var expires_in = res.data.token_info.expires_in.toString();
            var accesskey = res.data.token_info.access_token.toString();
            var refresh_token = res.data.token_info.refresh_token.toString();
            let cookies, csrf;
            res.data.cookie_info.cookies.forEach((item) => {
              if (item.name.includes('bili_jct'))
                csrf = item.value;
              cookies += `${item.name}=${item.value};`
            });
            var model = new loginCallback(mid, csrf, expires_in, accesskey, refresh_token, cookies);
            resolve(self.buildSuccessResult<loginCallback>(model));
          } else
            resolve(self.buildFailedResult<loginCallback>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<loginCallback>(e));
      }
    });
  }

  userInfo(mid: number): Promise<returnModel<userInfo>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new apiInfo('https://app.bilibili.com/x/v2/space', `vmid=${mid}`, true);
      this.client.getResult(info).then((res) => {
        try {
          if (res.code == 0) {
            let info: userInfo = res.data;
            resolve(self.buildSuccessResult<userInfo>(info));
          } else
            resolve(self.buildFailedResult<userInfo>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<userInfo>(e));
        }
      });
    });
  }

  getMine(): Promise<returnModel<homeUserCardModel>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new apiInfo('https://app.bilibili.com/x/v2/account/mine', '', true);
      this.client.getResult(info).then((res) => {
        try {
          if (res.code == 0) {
            let info = new homeUserCardModel();
            info.dynamic = res.data.dynamic;
            info.face = res.data.face;
            info.fans = res.data.follower;
            info.follow = res.data.following;
            info.level = res.data.level;
            info.mid = res.data.mid;
            info.name = res.data.name;
            info.vip_type = res.data.vip_type;
            resolve(self.buildSuccessResult<homeUserCardModel>(info));
          } else
            resolve(self.buildFailedResult<homeUserCardModel>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<homeUserCardModel>(e));
        }
      });
    });
  }

  follow(uid: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new dataInfo(`&act=1&fid=${uid}&re_src=31`, apiProvider.Build5);
      this.client.postResult("https://api.bilibili.com/x/relation/modify", info).then((res) => {
        try {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<any>(e));
        }
      });
    });
  }

  unFollow(uid: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new dataInfo(`&act=2&fid=${uid}&re_src=31`, apiProvider.Build5);
      this.client.postResult("https://api.bilibili.com/x/relation/modify", info).then((res) => {
        try {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<any>(e));
        }
      });
    });
  }

  getAtUser(pageIndex: number): Promise<returnModel<userAtList>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new apiInfo("http://api.live.bilibili.com/feed_svr/v1/feed_svr/get_user_info", `&page=${pageIndex}&pagesize=20&src=bilih5`, true);
      this.client.getResult(info).then((res) => {
        try {
          if (res.code == 0) {
            var data: userAtList = res;
            resolve(self.buildSuccessResult<userAtList>(data));
          } else
            resolve(self.buildFailedResult<userAtList>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<userAtList>(e));
        }
      });
    });
  }

  getUserSubmit(userId: number, pageNum: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      let info = new apiInfo('https://api.bilibili.com/x/space/wbi/arc/search',
        `mid=${userId}&ps=30&tid=0&pn=${pageNum}&keyword=&order=pubdate`, true);
      this.client.getResult(info).then((res) => {
        try {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>(res));
          else
            resolve(self.buildFailedResult<any>(res.message));
        } catch (e) {
          logger.error(e);
          resolve(self.buildExceptionResult<any>(e));
        }
      });
    });
  }
}
export default new userClient();